package com.corx.network.core.manager;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.corx.network.config.properties.NetworkConfig;
import com.corx.network.core.exception.NetworkException;
import com.corx.network.core.factory.NetworkFactory;
import com.corx.network.core.listener.ReceivedMessageListener;
import com.corx.network.core.model.ReceivedMessage;
import com.corx.network.core.model.SendMessage;
import com.corx.network.core.network.MqttNetwork;
import com.corx.network.core.network.MqttNetworkClient;
import com.corx.network.core.network.Network;
import com.corx.network.core.type.NetworkTypeEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gx
 * @version 1.0.0
 */
@Slf4j
public class NetworkManager {

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final int initialCapacity = 16;

    private final Map<String, Map<String, Network>> protocolNetworkMap = new ConcurrentHashMap<>(initialCapacity);


    /**
     * 注册网络组件
     */
    @SuppressWarnings("unchecked")
    public <T extends Network> T registerNetwork(NetworkConfig config) throws NetworkException {
        if (config.getKey() == null || config.getKey().isEmpty()) {
            throw new NetworkException("创建网络组件失败，[ config.key == null ]");
        }
        if (config.getType() == null) {
            throw new NetworkException("创建网络组件失败，[ config.type == null ] key：" + config.getKey());
        }
        if (contains(config.getKey(), config.getType())) {
            throw new NetworkException("创建[" + config.getType().getName() + "]网络组件失败，key已存在， key：" + config.getKey());
        }
        Network network = NetworkFactory.create(config);
        protocolNetworkMap
            .computeIfAbsent(config.getType().getType(), k -> new ConcurrentHashMap<>(initialCapacity))
            .put(config.getKey(), network);
        return (T) network;
    }

    /**
     * 获取网络组件
     */
    @SuppressWarnings("unchecked")
    public <T extends Network> T getNetwork(NetworkTypeEnum protocol, String key) {
        Map<String, Network> networks = protocolNetworkMap.get(protocol.getType());
        return networks == null ? null : (T) networks.get(key);
    }

    public void destroyNetwork(NetworkTypeEnum protocol, String key) {
        Map<String, Network> networks = protocolNetworkMap.get(protocol.getType());
        if (networks != null) {
            Network removed = networks.remove(key);
            if (removed != null) {
                removed.destroy();
            }
        }
    }

    public void destroyNetworkAll() {

        protocolNetworkMap.values().forEach(networkMap -> {
            networkMap.values().forEach(network -> {
                try {
                    network.destroy();
                    log.info("成功销毁网络实例: {}#{}", network.getType(), network.getKey());
                } catch (Exception e) {
                    log.warn("无法销毁网络实例: {}#{}", network.getType(), network.getKey(), e);
                }
            });
            networkMap.clear();
        });
        protocolNetworkMap.clear();
        log.debug("所有网络实例均已销毁");
    }

    public Map<String, Network> getNetworksByType(NetworkTypeEnum type) {
        return protocolNetworkMap.getOrDefault(type.getType(), new ConcurrentHashMap<>(initialCapacity));
    }

    public boolean contains(String key, NetworkTypeEnum type) {
        Map<String, Network> networks = protocolNetworkMap.get(type.getType());
        return networks != null && networks.containsKey(key);
    }


    public static void main(String[] args) throws Exception {
        MqttNetworkClient client = new MqttNetworkClient();
        client.setClientId(UUID.randomUUID().toString());
        client.setBrokerUrl("tcp://pet.corxnet.com:1883");
        client.setUsername("corxtest");
        client.setPassword("corx123456");
        client.connect();
        client.subscribe("a", 1, new ReceivedMessageListener<ReceivedMessage, ReceivedMessage>() {
            @Override
            protected ReceivedMessage doHandler(ReceivedMessage receivedMessage) {
                System.out.println(new String(receivedMessage.getPayload()));
                receivedMessage.setTranslatedPayload(new String(receivedMessage.getPayload()));
                return receivedMessage;
            }
        });


        String payload = "{\"A01\":110000,\"res\":\"123\"}";

        SendMessage message = SendMessage.builder("1b", "".getBytes())
            .build();

        client.sendMessage(message);

        System.out.println("发送的payload数据: " + new String(message.getPayload()));

        Thread.sleep(Long.MAX_VALUE);

        NetworkManager networkManager = new NetworkManager();
        MqttNetwork network = networkManager.getNetwork(NetworkTypeEnum.MQTT_CLIENT, "1");

    }


}
